#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <functional>
#include <QMouseEvent>
#include <QPushButton>
#include <sstream>
#include <QTimer>

QVector<QString> map_1 = {
    "1110101111",
    "1011111001",
    "1101100111",
    "0101001010",
    "1001111101",
    "1111011111",
    "1011111111",
    "1101101001",
    "1010111011",
    "1111011111",
};

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , r_map(map_1.size()), c_map(map_1[0].size())
    , map(r_map, QVector<MapSquare*>(c_map, nullptr))
    , src(new Unit(this)), dst(new Unit(this))
    , pushButton0(new QPushButton(this)), pushButton1(new QPushButton(this))
    , pushButton2(new QPushButton(this)), pushButton3(new QPushButton(this))
    , pushButton4(new QPushButton(this)), pushButton5(new QPushButton(this))
    , pushButton6(new QPushButton(this)), pushButton7(new QPushButton(this))
    , pushButton8(new QPushButton(this))
    , textEdit(new QTextEdit(this))
    , lineEdit_setsrcx(new QLineEdit(this))
    , lineEdit_setsrcy(new QLineEdit(this))
    , lineEdit_setdstx(new QLineEdit(this))
    , lineEdit_setdsty(new QLineEdit(this))
    , lineEdit_set_range(new QLineEdit(this))
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    resize(1500, 1100);
    initUI();
    connectUI();
    initMap();

    initUnit(src, MapSquare::UNIT_TYPE_PLAYER1);
    moveUnit(src, 4, 5);
    lineEdit_setsrcx->setText("4");
    lineEdit_setsrcy->setText("5");
    connectUnit(src);

    initUnit(dst, MapSquare::UNIT_TYPE_PLAYER2);
    moveUnit(dst, 2, 4);
    lineEdit_setdstx->setText("2");
    lineEdit_setdsty->setText("4");
    connectUnit(dst);

    // 连接 DFS 线程的信号
    connect(&dfsThread, &DfsThread::updateSquare, this, [this](int r, int c, MapSquare::STATUS status) {
        qDebug() << "子线程来信号了！" << status;
        map[r][c]->setStatus(status);
    });

    dst->move_range = 100;
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    if(dfsThreadIsRunning()) return;

    int c = event->x() / 100, r = event->y() / 100;
    qDebug() << r << ' ' << c;

    if(r < 0 || c < 0 || r >= r_map || c >= c_map){
        qDebug() << "未点击地图";
    } else {
        if (map[r][c]->status() == MapSquare::STATUS_MOVE) {
            qDebug() << map[r][c]->src_r() << ' ' << map[r][c]->src_c();
            moveUnit((Unit*)(map[map[r][c]->src_r()][map[r][c]->src_c()]->unit()), r, c);
        } else {
            qDebug() << "鼠标点击, 无事发生 ...";
        }
        resetMap();
    }
    QWidget::mousePressEvent(event);
}

void Widget::moveUnit(Widget::Unit *unit, int r, int c)
{
    if(unit->r != -1 && unit->c != -1) {
        map[unit->r][unit->c]->setUnitType(MapSquare::UNIT_TYPE_EMPTY);
        map[unit->r][unit->c]->setUnit();
    }
    unit->setGeometry(map[r][c]->geometry());
    unit->r = r;
    unit->c = c;
    unit->raise();
    map[r][c]->setUnitType(unit->unit_type);
    map[r][c]->setUnit(unit);
}

void Widget::initUI()
{
    textEdit->setGeometry(1050, 0, 200, 350);
    pushButton3->setGeometry(1050, 370, 200, 60);
    pushButton0->setGeometry(1050, 450, 200, 80);
    pushButton1->setGeometry(1050, 550, 200, 80);
    pushButton2->setGeometry(1050, 650, 200, 80);
    pushButton6->setGeometry(1050, 750, 200, 80);
    pushButton7->setGeometry(1050, 850, 200, 80);
    pushButton8->setGeometry(1050, 950, 200, 80);

    lineEdit_set_range->setGeometry(1260, 750, 90, 80);
    lineEdit_setsrcx->setGeometry(1260, 850, 80, 80);
    lineEdit_setsrcy->setGeometry(1360, 850, 80, 80);
    lineEdit_setdstx->setGeometry(1260, 950, 80, 80);
    lineEdit_setdsty->setGeometry(1360, 950, 80, 80);

    pushButton4->setGeometry(1260, 170, 180, 80);
    pushButton5->setGeometry(1260, 270, 180, 80);

    pushButton3->setText("设置地图(只支持10x10)");
    pushButton0->setText("连续执行");
    pushButton1->setText("暂停");
    pushButton2->setText("继续/下一步");
    pushButton6->setText("设置蓝点移动范围");
    pushButton7->setText("设置蓝点坐标");
    pushButton8->setText("设置红点坐标");
    pushButton4->setText("随机地图");
    pushButton5->setText("清空地图");

    QFont font;
    font.setPointSize(14);
    textEdit->setFont(font);

    font.setPointSize(20);
    lineEdit_set_range->setFont(font);
    lineEdit_setdstx->setFont(font);
    lineEdit_setdsty->setFont(font);
    lineEdit_setsrcx->setFont(font);
    lineEdit_setsrcy->setFont(font);

    updateTextEdit();
    lineEdit_set_range->setText("5");
}

void Widget::connectUI()
{
    connect(pushButton0, &QPushButton::clicked, this, [&]() {
        if (pushButton0->text() == "\u5355\u6b65\u6267\u884c") {
            pushButton0->setText("\u8fde\u7eed\u6267\u884c");
            dfsThread.oneStep(false);
        } else {
            pushButton0->setText("\u5355\u6b65\u6267\u884c");
            dfsThread.oneStep(true);
            pushButton1->setText("\u5df2\u6682\u505c");
        }
    });

    connect(pushButton1, &QPushButton::clicked, this, [&]() {
        dfsThread.pause();
        pushButton1->setText("\u5df2\u6682\u505c");
    });

    connect(pushButton2, &QPushButton::clicked, this, [&]() {
        src->clicked();
        dfsThread.resume();
        pushButton1->setText("\u6682\u505c");
    });

    connect(pushButton3, &QPushButton::clicked, this, [&]() {
        updateMapFromTextEdit();
        resetMap();
    });

    connect(pushButton4, &QPushButton::clicked, this, [&]() {
        emit pushButton5->clicked();
        for (auto& r : map_1) for (auto& c : r) c = (rand() % 100 < 20) ? '0' : '1';
        updateTextEdit();
    });

    connect(pushButton5, &QPushButton::clicked, this, [&]() {
        map_1 = QVector<QString>(10, QString(10, '1'));
        updateTextEdit();
    });

    connect(pushButton6, &QPushButton::clicked, this, [&]() {
        src->move_range = lineEdit_set_range->text().toInt();
    });

    connect(pushButton7, &QPushButton::clicked, this, [&]() {
        int r = lineEdit_setsrcx->text().toInt(), c = lineEdit_setsrcy->text().toInt();
        if(r < 0 || r >= map_1.size() || c < 0 || c >= map_1[0].size()){
            return;
        }
        moveUnit(src, r, c);
    });

    connect(pushButton8, &QPushButton::clicked, this, [&]() {
        int r = lineEdit_setdstx->text().toInt(), c = lineEdit_setdsty->text().toInt();
        if(r < 0 || r >= map_1.size() || c < 0 || c >= map_1[0].size()){
            return;
        }
        moveUnit(dst, r, c);
    });

    connect(&dfsThread, &DfsThread::updateSquare, this, [this](int r, int c, MapSquare::STATUS status) {
        map[r][c]->setStatus(status);
    });
}

void Widget::updateTextEdit()
{
    QString text;
    for (auto& r : map_1)
        text += r + "\n";
    textEdit->setText(text);
}

void Widget::updateMapFromTextEdit()
{
    QVector<QString> tmp;
    std::stringstream ss(textEdit->toPlainText().toStdString());
    std::string line;
    while (ss >> line) {
        tmp.push_back(line.c_str());
    }
    for (int i = 0; i < map_1.size(); i++) {
        if (tmp.size() <= i) break;
        for (int j = 0; j < map_1[0].size(); j++) {
            if (tmp[i].size() <= j) break;
            map_1[i][j] = tmp[i][j];
        }
    }
}

void Widget::initUnit(Widget::Unit *unit, MapSquare::UNIT_TYPE unit_type)
{
    if(unit_type == MapSquare::UNIT_TYPE_PLAYER1)
        unit->setIcon(Pixmaps::getInstance()->map_src);
    else if(unit_type == MapSquare::UNIT_TYPE_PLAYER2)
        unit->setIcon(Pixmaps::getInstance()->map_dst);
    else
        qDebug() << "初始化单位为未定义类型";
    unit->setIconSize(QSize(80, 80));
    unit->setStyleSheet("border : transparent;");
    unit->unit_type = unit_type;
}


void Widget::initMap()
{
    for(int r = 0; r < r_map; r++){
        for(int c = 0; c < c_map; c++){
            map[r][c] = new MapSquare(this);
            map[r][c]->setGeometry(100*c, 100*r, 100, 100);
            map[r][c]->setIndex(r, c);
        }
    }
    resetMap();
}


void Widget::resetMap()
{
    for(int r = 0; r < r_map; r++) for(int c = 0; c < c_map; c++){
        map[r][c]->setSrc();
        if(map[r][c]->unit_type() != MapSquare::UNIT_TYPE_EMPTY){
            map[r][c]->setStatus(MapSquare::STATUS_EMPTY);
            continue;
        }
        if(map_1[r][c] == '1') map[r][c]->setStatus(MapSquare::STATUS_EMPTY);
        else map[r][c]->setStatus(MapSquare::STATUS_UNCHECKABLE);
    }
}

bool Widget::dfsThreadIsRunning()
{
    if (dfsThread.isRunning()) {
        qDebug() << "DFS is already running, waiting for it to finish...";
        return true;
    }
    return false;
}

void Widget::connectUnit(Widget::Unit* &unit)
{
    connect(unit, &QPushButton::clicked, this, [&](){
//        return;
        qDebug() << "unit clicked ...";
        if(dfsThreadIsRunning()) return;
        MapSquare::STATUS _status = map[unit->r][unit->c]->status();

        if(_status == MapSquare::STATUS_EMPTY) {
            resetMap(); // 重置地图
            dfsThread.init(map, unit->r, unit->c, unit->move_range); // 每次都要初始化
            dfsThread.start(); // 不能用run, 会阻塞主线程
        } else {
            resetMap(); // 重置地图
        }
    });
}


